package com.example.demo.core.web.core.utils.converter;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import java.util.*;
import org.dromara.hutool.core.bean.BeanUtil;
import org.modelmapper.ModelMapper;
import org.modelmapper.config.Configuration;
import org.modelmapper.convention.MatchingStrategies;
import org.modelmapper.convention.NameTokenizers;

/**
 * 转换工具类
 *
 * @author Caratacus
 */
public class ConverterUtils {
  /**
   * Bean转换为Map
   *
   * @param bean
   * @param <T>
   * @return
   */
  public static <T> Map<String, Object> beanToMap(T bean) {
    return BeanUtil.beanToMap(bean);
  }

  /**
   * List<E>转换为List<Map<String, Object>>
   *
   * @param objList
   * @param <T>
   * @return
   */
  public static <T> List<Map<String, Object>> beansToMap(List<T> objList) {
    List<Map<String, Object>> list = Collections.emptyList();
    if (CollectionUtils.isNotEmpty(objList)) {
      list = new ArrayList<>(objList.size());
      Map<String, Object> map;
      T bean;
      for (T anObjList : objList) {
        bean = anObjList;
        map = beanToMap(bean);
        list.add(map);
      }
    }
    return list;
  }

  /**
   * map转为bean
   *
   * @param <T> the type parameter
   * @param mapList the map list
   * @param beanClass the bean class
   * @return t list
   */
  public static <T> List<T> mapToBeanList(List<Map<String, Object>> mapList, Class<T> beanClass) {
    List<T> list = Collections.emptyList();
    if (CollectionUtils.isNotEmpty(mapList)) {
      list = new ArrayList<>(mapList.size());
      for (Map<String, Object> map : mapList) {
        T bean = mapToBean(map, beanClass);
        list.add(bean);
      }
    }
    return list;
  }

  /**
   * map转为bean
   *
   * @param map the map
   * @param beanClass the bean class
   * @return t
   */
  public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
    return BeanUtil.toBean(map, beanClass);
  }

  public static <T> T map(Object source, Class<T> targetCls) {
    return BeanUtil.toBean(source, targetCls);
  }

  public static <T> List<T> mapList(List<Object> sourceList, Class<T> targetCls) {
    List<T> list = Collections.emptyList();
    if (CollectionUtils.isNotEmpty(sourceList)) {
      list = new ArrayList<>(sourceList.size());
      for (Object source : sourceList) {
        T bean = map(source, targetCls);
        list.add(bean);
      }
    }
    return list;
  }

  /**
   * 此时支持源是下划线和驼峰
   *
   * @param source
   * @param targetCls
   * @param <T>
   * @return
   */
  public static <T> T underscoreMap(Object source, Class<T> targetCls) {
    return snakeCaseMap(source, targetCls);
  }

  /**
   * 此时支持源是下划线和驼峰
   *
   * @param source
   * @param targetCls
   * @param <T>
   * @return
   */
  public static <T> T snakeCaseMap(Object source, Class<T> targetCls) {
    ModelMapper modelMapper = new ModelMapper();
    Configuration configuration = modelMapper.getConfiguration();
    configuration.setSourceNameTokenizer(NameTokenizers.UNDERSCORE);
    configuration.setFullTypeMatchingRequired(true);
    configuration.setMatchingStrategy(MatchingStrategies.STRICT);
    configuration.setAmbiguityIgnored(true);
    return modelMapper.map(source, targetCls);
  }

  public static <T> T camelCaseMap(Object source, Class<T> targetCls) {
    ModelMapper modelMapper = new ModelMapper();
    Configuration configuration = modelMapper.getConfiguration();
    configuration.setSourceNameTokenizer(NameTokenizers.CAMEL_CASE);
    configuration.setFullTypeMatchingRequired(true);
    configuration.setMatchingStrategy(MatchingStrategies.STRICT);
    configuration.setAmbiguityIgnored(true);
    return modelMapper.map(source, targetCls);
  }
}
